package cn.edu.ccut.refactor;

import java.util.*;
import org.eclipse.core.filebuffers.*;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.*;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.TextFileChange;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.ReplaceEdit;

import edu.ccut.saturn.studio.core.search.SaturnFileSearcher;
import edu.ccut.saturn.studio.core.search.SaturnFileSearcher.SearchResult;

/**
 * 
 * @author Bai Yucheng 2008-1-10
 * 
 */
public final class SearchEngine {
	private Map<IFile, Replacement[]> fReference;
	private IResource fResource;
	private HashMap<String, String> fKeyMap;
	int flag;

	class Replacement {

		IRegion region;
		String keyword;

		Replacement() {
		}
	}

	public SearchEngine(IResource iresource, String s, String s1, int f) {
		fReference = new HashMap<IFile, Replacement[]>(10);
		fResource = iresource;
		HashMap<String, String> hashmap = new HashMap<String, String>();
		hashmap.put(s, s1);
		fKeyMap = hashmap;
		flag = f;
	}

//	public SearchEngine(IResource iresource, HashMap<String, String> hashmap) {
//		fReference = new HashMap<IFile, Replacement[]>(10);
//		fResource = iresource;
//		fKeyMap = hashmap;
//	}

	private Replacement[] getReplacement(IFile ifile) {
		return (Replacement[]) fReference.get(ifile);
	}

	private IFile[] getMatchedFiles() {
		Set<IFile> set = fReference.keySet();
		return (IFile[]) set.toArray(new IFile[set.size()]);
	}

	public Change[] getChanges() {
		ArrayList<Object> arraylist = new ArrayList<Object>();
		IFile aifile[] = getMatchedFiles();
		if (aifile.length == 0)
			return new Change[0];
		for (int i = 0; i < aifile.length; i++) {
			IFile ifile = aifile[i];
			Replacement areplacement[] = getReplacement(ifile);
			Object obj = new SaturnTextFileChange(ifile.getName(), ifile);
			MultiTextEdit multitextedit = new MultiTextEdit();
			((TextFileChange) (obj)).setEdit(multitextedit);
			for (int j = 0; j < areplacement.length; j++) {
				Replacement replacement = areplacement[j];
				String oldKey;
				String key = replacement.keyword;
				String newKey;
				String ss;
				IRegion iregion = replacement.region;

					if (ifile.toString().endsWith("config") && key.endsWith("jsp")) {
						ss = ifile.getProject().toString().replace("P/", "");
						key = "/" + ss + key;
						oldKey = key;
						newKey = (String) fKeyMap.get(oldKey).replace("/" + ss , "");
					} else {
						oldKey = key;
						newKey = (String) fKeyMap.get(oldKey);
					}
					
				multitextedit.addChild(new ReplaceEdit(iregion.getOffset(),
						iregion.getLength(), newKey));
			}
			arraylist.add(obj);
		}

		return (Change[]) arraylist.toArray(new Change[arraylist.size()]);
	}

	public Change[] search(IProgressMonitor iprogressmonitor)
			throws CoreException {
		iprogressmonitor.setTaskName("start");
		iprogressmonitor.worked(1);
		Set<String> set = fKeyMap.keySet();
		if (fResource instanceof IContainer) {
			try {
				IFile aifile[] = getResource((IContainer) fResource);
				String s1;
				for (Iterator<String> iterator1 = set.iterator(); iterator1
						.hasNext(); findMatch(aifile, s1, iprogressmonitor))
					s1 = (String) iterator1.next();

			} catch (Exception e) {
				e.printStackTrace();
			}
		} else {
			String s;
			for (Iterator<String> iterator = set.iterator(); iterator.hasNext(); findMatch(
					(IFile) fResource, s, iprogressmonitor))
				s = (String) iterator.next();

		}
		return getChanges();
	}

	private void findMatch(IFile aifile[], String s,
			IProgressMonitor iprogressmonitor) throws CoreException {
		
		for (int i = 0; i < aifile.length; i++) {
			String s1 = "findmatch: " + aifile[i].getName();
			if (s1.endsWith("authority.config") && s.endsWith("jsp")) {
				String ss = s.split("/")[1];
				s = s.replace("/" + ss, "");
				fKeyMap.toString().replace("/" + ss, "");
			}
			iprogressmonitor.setTaskName(s1);
			findMatch(aifile[i], s, iprogressmonitor);
			iprogressmonitor.worked(1);
		}

	}


	private IFile[] getResource(IContainer icontainer) {
		String[] searchType = { "logic", "action","jsp","saturndata","component","validate","wf","config"};
		try {
			List<SearchResult> searchResults = SaturnFileSearcher
					.getValueAndDocumentMapInProjectWithOutJar(
							(IProject) fResource, searchType, null);
			
			IFile[] IFiles = new IFile[searchResults.size()];
			int i=0;
			
			for (SearchResult searchResult: searchResults) {
				
				 IFile[] findFilesForLocationURI = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(searchResult.getFile().toURI());
				 IFiles[i]= findFilesForLocationURI[0];
				 i++;
			}
			return IFiles;
		} catch (Exception e) {
			e.printStackTrace();
		}
	return null;
	}

	private void findMatch(IFile ifile, String oldKey,
			IProgressMonitor iprogressmonitor) throws CoreException {
		ArrayList<Replacement> arraylist;
		IDocument idocument = acquireDocument(ifile, iprogressmonitor);
		FindReplaceDocumentAdapter findreplacedocumentadapter = new FindReplaceDocumentAdapter(
				idocument);
		int i = 0;
		arraylist = new ArrayList<Replacement>();

		try {

			while (i != -1) {
				IRegion iregion = findreplacedocumentadapter.find(i, oldKey,
						true, false, false, false);
				if (iregion != null) {
					i = iregion.getOffset() + iregion.getLength();

					Replacement replacement = new Replacement();
					replacement.keyword = oldKey;
					replacement.region = iregion;
					arraylist.add(replacement);

				} else {
					i = -1;
				}
			}

		} catch (Exception _ex) {
		} finally {
			releaseDocument(ifile, iprogressmonitor);
		}
		if (arraylist.size() > 0) {
			if (fReference.containsKey(ifile)) {
				Replacement areplacement[] = getReplacement(ifile);
				for (int k = 0; k < areplacement.length; k++)
					arraylist.add(areplacement[k]);
			}
			fReference.put(ifile, (Replacement[]) arraylist
					.toArray(new Replacement[arraylist.size()]));
		}
		return;
	}

	@SuppressWarnings("deprecation")
	private void releaseDocument(IFile ifile, IProgressMonitor iprogressmonitor)
			throws CoreException {
		ITextFileBufferManager itextfilebuffermanager = FileBuffers
				.getTextFileBufferManager();
		IPath ipath = ifile.getFullPath();
		itextfilebuffermanager.disconnect(ipath, iprogressmonitor);
	}

	@SuppressWarnings("deprecation")
	private IDocument acquireDocument(IFile ifile,
			IProgressMonitor iprogressmonitor) throws CoreException {
		ITextFileBufferManager itextfilebuffermanager = FileBuffers
				.getTextFileBufferManager();
		IPath ipath = ifile.getFullPath();
		itextfilebuffermanager.connect(ipath, iprogressmonitor);
		ITextFileBuffer itextfilebuffer = itextfilebuffermanager
				.getTextFileBuffer(ipath);
		if (itextfilebuffer.getModificationStamp() != ifile
				.getModificationStamp())
			itextfilebuffer.revert(iprogressmonitor);
		return itextfilebuffer.getDocument();
	}

}
